package edu.ucsd.ccdb.tagPopup;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.text.BadLocationException;
import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;

import edu.ucsd.ccdb.tagPopup.dataType.NIFOntologyTerm;
import edu.ucsd.ccdb.tagPopup.othologyService.NifServiceWrapper;
import edu.ucsd.ccdb.tagPopup.util.SummaryPaneRefresher;
import edu.ucsd.irods.IRODSFileString;
import edu.ucsd.irods.SQLDBQuery;

public class OnthoTabBackup extends JPanel implements DocumentListener, ListSelectionListener, ActionListener  {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private static enum Mode {INSERT, AUTOCOMPLETE, MOUSECOMPLETE};
	private static final String COMMIT_ACTION = "commit";
	private Mode mode; 

//	String[] petStrings = { "bird", "cat", "dog", "rabbit", "pig" };
	
	JTextField typingField ;
	JList suggestField;
	DefaultListModel listModel;
	
	// data
	Integer MPID;
	IRODSFileString file;
	JPanel summaryPane;
	
	public OnthoTabBackup (Integer MPID, IRODSFileString file, JPanel summaryPane) {
		
		this.MPID = MPID;
		this.file = file;
		this.summaryPane = summaryPane;
		
		mode = Mode.INSERT;
		listModel = new DefaultListModel();
		
		typingField = new JTextField(5);
		suggestField = new JList(listModel);
		JButton button = new JButton ("Add tag");
		
		// ------------Add action listener to button---------
		button.addActionListener(this);
		
		//-------------SETTING UP THE TYPYING FIELD-----------
		// add typing field attributes
		typingField.getDocument().addDocumentListener(this);
		// set keymap for the typing Field
		InputMap im = typingField.getInputMap();
		ActionMap am = typingField.getActionMap();
		im.put(KeyStroke.getKeyStroke("ENTER"), COMMIT_ACTION);
		am.put(COMMIT_ACTION, new CommitAction() );
		
		
		//------------SETTING UP THE SUGGEST FIELD--------------
		suggestField.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
		suggestField.setLayoutOrientation(JList.VERTICAL);
		suggestField.addListSelectionListener(this);
		
		typingField.setEditable(true);
		
		// populate suggestiveField		
		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		add (typingField);
		add (Box.createRigidArea(new Dimension(0,7) ));
		add ( new JScrollPane( suggestField ) );
		add (button);
	}
	
	private void fillSuggestField ( List<String> data ) {
		listModel.clear();
		for (String element: data) {
//			suggestField.append(element + "\n" );
			listModel.addElement(element);
		}
	}

	public void changedUpdate(DocumentEvent e) {
	}


	public void removeUpdate(DocumentEvent e) {
	}
	
	public void insertUpdate(DocumentEvent e) {
	
		// error check
		suggestField.clearSelection();
		
		if (e.getLength() != 1 ){
			return;			
		}
		
		int pos = e.getOffset();
		String content = null ;
		
		try {
			content = typingField.getText (0, pos + 1) ;
		}
		catch (BadLocationException e1 ){
			e1.printStackTrace();
		}
		
		// find where the word starts
		int w;
		for (w = pos; w >=0 ; w -- ) {
			if (! Character.isLetter(content.charAt(w))) {
				break;
			}
		}
		
		if (pos - w  <3 ) {
			return;	// too few character
		}
		
		String prefix = content.substring(w + 1 ).toLowerCase();

		// fill the list
//		List<String> list = Arrays.asList(petStrings)  ;
		List<String> list = new ArrayList<String>();
		try {
			list = NifServiceWrapper.getAutoRequestList(prefix);
		} catch (Exception e1) {
			e1.printStackTrace();
		}

		fillSuggestField(list);
		
		Collections.sort(list);
		int n = Collections.binarySearch( list, prefix);
		
		if (n < 0 && -n <= list.size() ) {
			String match = list.get(-n - 1);
			
			if (match.startsWith(prefix)){
				String completion = match.substring(pos - w);
				
				// submit change
				
				SwingUtilities.invokeLater(new CompletionTask (completion, pos + 1) );
			}
		}
		else {
			mode = Mode.INSERT;
		}
	}

	
	private class CompletionTask implements Runnable {

		String completion;
		int position;


		public CompletionTask (String completion, int position) {
			this.completion = completion;
			this.position = position;
		}
		
		public void run() {
			try {
				typingField.getDocument().insertString(position, completion, null);
			} catch (BadLocationException e) {
				e.printStackTrace();
			}
			typingField.setCaretPosition(position + completion.length() );
			typingField.moveCaretPosition(position );
			
			mode = Mode.AUTOCOMPLETE;
		}
	}
	
	private class CommitAction extends AbstractAction {

		private static final long serialVersionUID = 1L;

		public void actionPerformed(ActionEvent e) {
			
			if (mode == Mode.AUTOCOMPLETE ) {
				int pos = typingField.getSelectionEnd();
//					typingField.getDocument().insertString(pos, " ", null);
				typingField.setCaretPosition(pos);
				
				mode = Mode.INSERT;
			}
			else {
				typingField.replaceSelection("\n");
			}		
			
		}
	}

	/*
	 * (non-Javadoc) for the suggestFiled when doulble-clicking
	 * @see javax.swing.event.ListSelectionListener#valueChanged(javax.swing.event.ListSelectionEvent)
	 */
	public void valueChanged(ListSelectionEvent e) {

		if (!e.getValueIsAdjusting()) {
			JList list = (JList) e.getSource();
			
			if (!list.isSelectionEmpty()) {
				mode = Mode.MOUSECOMPLETE;
				SwingUtilities.invokeLater(new MouseChangeValue(list));
			}
		}
	}
	
	private class MouseChangeValue  implements Runnable {
		
		JList list;
		
		public MouseChangeValue( JList list) {
			this.list = list;
		}
		
		public void run() {
			
			if (mode == Mode.MOUSECOMPLETE) {
				String data = (String) list.getSelectedValue();
				typingField.setText(data);
				typingField.setCaretPosition(typingField.getSelectionEnd());
								
				mode = Mode.INSERT;
			}
		}
	}

	public void actionPerformed(ActionEvent e) {
		
		String concept = typingField.getText();
		
		NIFOntologyTerm data = null;
		try {
			data = NifServiceWrapper.getConcept(concept);
		} catch (ParserConfigurationException e1) {
			e1.printStackTrace();
		} catch (SAXException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		
		System.out.println (data == null ? "Null" : data.toString());
		//TODO insert to database, change the screenName
		
		if (data != null) {
			try {
//				SQLDBQuery.manageInsertNewTagOnthology(file.getAbsolutePath(), 
//							IRODSConfiguration.LOGIN_USERNAME , MPID, data.getLabel(), data.getUrl());
				SQLDBQuery.manageInsertNewTagOnthology(file.getAbsolutePath(), 
						"wawong8" , MPID, data.getLabel(), data.getOntoURL());
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}
		// do refresh
		if (summaryPane != null )
			SummaryPaneRefresher.doRefreshAction( "wawong8", MPID, file, summaryPane);
		else 
			System.out.println ("Summmary Pane is null");
		
	}
}
